package com.lmmob.autotest.uitest.pages;

import java.util.List;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.internal.seleniumemulation.JavascriptLibrary;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.lmmob.autotest.uitest.exception.ElementNotFoundException;


public class ElementFinder {
	
    private final Logger log = LoggerFactory.getLogger(ElementFinder.class);

	WebDriver driver;

	public  ElementFinder(WebDriver driver)
	{
		this.driver=driver;
	}
	
	public WebElement findElementById(String target) 
	{
		WebElement element=null;
		try {
			element = driver.findElement(By.id(target));
		} catch (Exception e) {
			log.info("can't find this element.");
		}		
		return element;
	}
	
	public WebElement findElementByName(String target)
	{
		WebElement element=null;
		try {
			element = driver.findElement(By.name(target));
		} catch (Exception e) {
			log.info("can't find this element.");
		}
		return element;
	}
	
	public WebElement findElementByLinkText(String target)
	{
		WebElement element=null;
		try {
			element = driver.findElement(By.linkText(target));
		} catch (Exception e) {
			log.info("can't find this element.");
		}
		return element;
		
	}
	
	public WebElement findElementByClassName(String target)
	{
		WebElement element=null;
		try {
			element = driver.findElement(By.className(target));
		} catch (Exception e) {
			log.info("can't find this element.");
		}
		return element;
	}
	
	public WebElement findElementByCssSelector(String target)
	{
		WebElement element=null;
		try {
			element = driver.findElement(By.cssSelector(target));
		} catch (Exception e) {
			log.info("can't find this element.");
		}
		return element;
	}
	
	public WebElement findElementByTagName(String target)
	{
		WebElement element=null;
		try {
			element = driver.findElement(By.tagName(target));
		} catch (Exception e) {
			log.info("can't find this element.");
		}
		return element;
	}
	
	public WebElement findElementByXPath(String target)
	{
		WebElement element=null;
		try {
			element = driver.findElement(By.xpath(target));
		} catch (Exception e) {
			log.info("can't find this element.");
		}
		return element;
	}
	
	public WebElement findElementByPartialLinkText(String target)
	{
		WebElement element=null;
		try {
			element = driver.findElement(By.partialLinkText(target));
		} catch (Exception e) {
			log.info("can't find this element.");
		}
		return element;
	}
	
	public List<WebElement> findElementsById(String target) 
	{
		List<WebElement> elements=null;
		try {
			elements = driver.findElements(By.id(target));
		} catch (Exception e) {
			log.info("can't find this element:"+target);
		}		
		return elements;
	}
	
	public List<WebElement> findElementsByName(String target)
	{
		List<WebElement> elements=null;
		try {
			elements = driver.findElements(By.name(target));
		} catch (Exception e) {
			log.info("can't find this element:"+target);
		}		
		return elements;
	}
	
	public List<WebElement> findElementsByLinkText(String target)
	{
		List<WebElement> elements=null;
		try {
			elements = driver.findElements(By.linkText(target));
		} catch (Exception e) {
			log.info("can't find this element:"+target);
		}		
		return elements;
		
	}
	
	public List<WebElement> findElementsByClassName(String target)
	{
		List<WebElement> elements=null;
		try {
			elements = driver.findElements(By.className(target));
		} catch (Exception e) {
			log.info("can't find this element:"+target);
		}		
		return elements;
	}
	
	public List<WebElement> findElementsByCssSelector(String target)
	{
		List<WebElement> elements=null;
		try {
			elements = driver.findElements(By.cssSelector(target));
		} catch (Exception e) {
			log.info("can't find this element:"+target);
		}		
		return elements;
	}
	
	public List<WebElement> findElementsByTagName(String target)
	{
		List<WebElement> elements=null;
		try {
			elements = driver.findElements(By.tagName(target));
		} catch (Exception e) {
			log.info("can't find this element:"+target);
		}		
		return elements;
	}
	
	public List<WebElement> findElementsByXPath(String target)
	{
		List<WebElement> elements=null;
		try {
			elements = driver.findElements(By.xpath(target));
		} catch (Exception e) {
			log.info("can't find this element:"+target);
		}		
		return elements;
	}
	
	public List<WebElement> findElementsByPartialLinkText(String target)
	{
		List<WebElement> elements=null;
		try {
			elements = driver.findElements(By.partialLinkText(target));
		} catch (Exception e) {
			log.info("can't find this element:"+target);
		}		
		return elements;
	}
	
	public WebElement findElementByTraverse(String locator)
	{
		if(this.findElementById(locator)!=null)
		{
			return this.findElementById(locator);
		}else if(this.findElementByName(locator)!=null)
		{
			return this.findElementByName(locator);
		}else if(this.findElementByLinkText(locator)!=null)
		{
			return this.findElementByLinkText(locator);
		}else if(this.findElementByPartialLinkText(locator)!=null)
		{
			return this.findElementByPartialLinkText(locator);
		}else if(this.findElementByTagName(locator)!=null)
		{
			return this.findElementByTagName(locator);
		}else if(this.findElementByXPath(locator)!=null)
		{
			return this.findElementByXPath(locator);
		}else if(this.findElementByCssSelector(locator)!=null)
		{
			return this.findElementByCssSelector(locator);
		}else if(this.findElementByClassName(locator)!=null)
		{
			return this.findElementByClassName(locator);
		}else
		{
			return null;
		}
	}
	
	public WebElement findElementByPrefix(String locator)
	{
		String target=locator.trim();
		if(target.startsWith("id="))
		{
			locator = locator.substring("id=".length());
			return driver.findElement(By.id(locator));
		}else if(target.startsWith("name="))
		{
			locator = locator.substring("name=".length());
			return driver.findElement(By.name(locator));
		}else if(target.startsWith("link="))
		{
			locator = locator.substring("link=".length());
			return driver.findElement(By.linkText(locator));
		}else if(target.startsWith("css="))
		{
			locator = locator.substring("css=".length());
			return driver.findElement(By.cssSelector(locator));
		}else if(target.startsWith("//")||target.startsWith("/")||target.startsWith("xpath="))
		{
			locator = locator.substring("xpath=".length());
			return driver.findElement(By.xpath(locator));
		}else
		{
			log.info("can't find element by prefix.");
			return null;
		}
	}
	

	public List<WebElement> findElementsByPrefix(String locator)
	{
		String target=locator.trim();
		if(target.startsWith("id="))
		{
			locator = locator.substring("id=".length());
			return driver.findElements(By.id(locator));
		}else if(target.startsWith("name="))
		{
			locator = locator.substring("name=".length());
			return driver.findElements(By.name(locator));
		}else if(target.startsWith("link="))
		{
			locator = locator.substring("link=".length());
			return driver.findElements(By.linkText(locator));
		}else if(target.startsWith("css="))
		{
			locator = locator.substring("css=".length());
			return driver.findElements(By.cssSelector(locator));
		}else if(target.startsWith("//")||target.startsWith("/")||target.startsWith("xpath="))
		{
			locator = locator.substring("xpath=".length());
			return driver.findElements(By.xpath(locator));
		}else
		{
			log.info("can't find element by prefix.");
			return null;
		}
	}
	
	public List<WebElement> findElementsByTraverse(String locator)
	{
		if(this.findElementById(locator)!=null)
		{
			return this.findElementsById(locator);
		}else if(this.findElementByName(locator)!=null)
		{
			return this.findElementsByName(locator);
		}else if(this.findElementByLinkText(locator)!=null)
		{
			return this.findElementsByLinkText(locator);
		}else if(this.findElementByPartialLinkText(locator)!=null)
		{
			return this.findElementsByPartialLinkText(locator);
		}else if(this.findElementByTagName(locator)!=null)
		{
			return this.findElementsByTagName(locator);
		}else if(this.findElementByXPath(locator)!=null)
		{
			return this.findElementsByXPath(locator);
		}else if(this.findElementByCssSelector(locator)!=null)
		{
			return this.findElementsByCssSelector(locator);
		}else if(this.findElementByClassName(locator)!=null)
		{
			return this.findElementsByClassName(locator);
		}else
		{
			return null;
		}
	}
	
	public WebElement getElement(String target)
	{
		WebElement element;
		element=findElementByPrefix(target);
		if(element!=null)
		{
			return element;
		}else if((element=findElementByTraverse(target))!=null)
		{
			return element;
		}else
		{
			throw new ElementNotFoundException("can't find element: "+target+"  in this page.");
		}
	}
	
	public WebElement findElement(String target)
	{
		WebElement element=null;		
		JavascriptLibrary library=new JavascriptLibrary();
		org.openqa.selenium.internal.seleniumemulation.ElementFinder finder=new org.openqa.selenium.internal.seleniumemulation.ElementFinder(library);
		try {
			element=finder.findElement(driver, target);
		} catch (Exception e) {
			element=findElementByPrefix(target);
			if(element==null)
			{
				element=findElementByTraverse(target);
			}			
			log.error("can't find element: "+target+"  in this page.");
		}
		return element;
	
	}
	
	public List<WebElement> findElements(String target)
	{
		List<WebElement> elements;
		elements=findElementsByPrefix(target);
		if(elements!=null&&elements.size()>0)
		{
			return elements;
		}else if((elements=findElementsByTraverse(target))!=null&&elements.size()>0)
		{
			return elements;
		}else
		{
			throw new ElementNotFoundException("can't find element: "+target+"  in this page.");
		}
	}
}
